package seiacpsjava;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;

import seiacpsjava.sortalgorithms.SortAlgorithm;
import seiacpsjava.sortalgorithms.SortAlgorithmFactory;
import seiacpsjava.utilities.FileParser;
import seiacpsjava.utilities.MemoryService;
import seiacpsjava.utilities.MemoryStatistics;




public class Sort {

	
	static String sortAlgorithm;
	static SortAlgorithm algorithm ;
	static String inputFile;
	static String outputFile;
	static int[] items;
	static String outputText = "";
	static MemoryStatistics memoryStatistics;
	
	static long fileParsingExecutionTime;
	static long fileWritingExecutionTime;
	
	
	public static void main(String[] args) {
				
		if ( args.length >= 3 ){
			
		sortAlgorithm = args[0];
		inputFile = args[1];
		outputFile = args[2];
			
		switch (sortAlgorithm) {
		case "bubblesort":
			algorithm = SortAlgorithmFactory.getBubbleSortAlgorithm();		
			break;
		case "selectionsort":
			algorithm = SortAlgorithmFactory.getSelectionSortAlgorithm();
			break;
		default:
			System.out.println(args[0] + " is not a supported sorting algorithm.");
			return;	
		}
		
		Path inputFilePath = FileSystems.getDefault()
				.getPath(inputFile);
		
		long parsingStart = System.nanoTime();
		FileParser parser = new FileParser(inputFilePath);		
		long parsingEnd = System.nanoTime();
		
		fileParsingExecutionTime = parsingEnd -parsingStart;
		
		try {
			items = parser.getNumbers();
			//MemoryService memService = new MemoryService(10);
			//memService.startRecording();
			algorithm.sort(items);
			//memoryStatistics = memService.endRecording();
			memoryStatistics = new MemoryStatistics();
			memoryStatistics.updateMemoryTotals();
			memoryStatistics.calculateMemoryRunningAvg();
			
			outputText = generateOutput();
			
			long writingStart = System.nanoTime();
			writeToFile(outputText,outputFile,false);
			long writingEnd = System.nanoTime();
			
			fileWritingExecutionTime = writingEnd - writingStart;
			
			outputText = getStatistics();
			
			writeToFile(outputText,outputFile,true);
			
			System.out.println("Generated output file : " + outputFile);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		}else{
						
			System.out.println("Usage: Sort <sort_algorithm> <input_file> <output_file>");
		}
		
	

	}
	
	private static void writeToFile(String output, String filePath, boolean isAppendModeOn) {
		try{
			  // Create file 
			  FileWriter fstream = new FileWriter(filePath,isAppendModeOn);
			  BufferedWriter out = new BufferedWriter(fstream);
			  out.write(output);
			  //Close the output stream
			  out.close();
		 }catch (Exception e){//Catch exception if any
			  System.err.println("Error: " + e.getMessage());
		 }
	}
	
	public static String getStatistics(){
		StringBuffer output = new StringBuffer();
		
		String line = "==================================================================================";
		String fileParsing  = "File Parsing Time (Nano Seconds) : " + fileParsingExecutionTime;
		String algorithmName = "Algorithm Name : " + algorithm.getAlgorithmName();		
		String noInnerLoops  = "No. of Inner Loops : " + algorithm.getNumberOfInnerLoops();
		String noOuterLoops  = "No. of Outer Loops : " + algorithm.getNumberOfOuterLoops();
		String noSwaps  = "No. of Swaps : " + algorithm.getNumberOfSwaps();
		String executionTime = "Sorting Execution Time (Nano Seconds) : " + algorithm.getExecutionTime();
		String fileWriting   = "File Writing Time (Nano Seconds) : " + fileWritingExecutionTime;
		String usedMemory = "Memory Used (Bytes) : " + memoryStatistics.getUsedMemoryRunningAvg();
		
		output.append(line + "\r\n");
		output.append(algorithmName+ "\r\n");
		output.append(fileParsing + "\r\n");
		output.append(noInnerLoops+ "\r\n");
		output.append(noOuterLoops+ "\r\n");
		output.append(noSwaps+ "\r\n");
		output.append(executionTime+ "\r\n");
		output.append(fileWriting + "\r\n");
		output.append(usedMemory +"\r\n");
		output.append(line);
		
		return output.toString();
		
	}
	
	public static String generateOutput()
	{
		StringBuffer output = new StringBuffer();
		
		for (int i=0 ; i < items.length; i++)
		{
			if ( i < items.length-1){
				output.append(items[i]+ ",");
			}else{
				output.append(items[i] + "\r\n");
			}
		}
				
		return output.toString();
	}
}
